// Начинаем выполнять JS-код после события
// окончания загрузки страницы
$(function(){
	var _addStatisticViewModel = function(self){
		self.issuesGroupedByStatus = ko.computed(function(){
			var groupedIssues = [];
			ko.utils.arrayForEach(all.issueStatuses(), function(issueStatus){
				var issuesCount = 0;
				ko.utils.arrayForEach(all.issues(), function(issue){
					if(issueStatus.isSame(issue.status())){
						issuesCount++;
					}
				});
				groupedIssues.push({
					name: issueStatus.name(),
					summary: issuesCount,
					percent: parseInt(issuesCount / all.issues().length * 100)
				});
			});
			groupedIssues.sort(function(a, b){
				return a.summary < b.summary;
			});
			return groupedIssues;
		});
		self.issuesGroupedByType = ko.computed(function(){
			var groupedIssues = [];
			ko.utils.arrayForEach(all.issueTypes(), function(issueType){
				var issuesCount = 0;
				ko.utils.arrayForEach(all.issues(), function(issue){
					if(issueType.isSame(issue.type())){
						issuesCount++;
					}
				});
				groupedIssues.push({
					name: issueType.name(),
					summary: issuesCount,
					percent: parseInt(issuesCount / all.issues().length * 100)
				});
			});
			return groupedIssues;
		});
		self.progressValue = ko.computed(function(){
			var issuesCount = 0;
			ko.utils.arrayForEach(all.issues(), function(issue){
				if(issue.isVerified()){
					issuesCount++;
				}
			});
			return parseInt(issuesCount / all.issues().length * 100);
		});
		self.progressText = ko.computed(function(){
			return 'Выполнен на ' + self.progressValue() + '%';
		});
		self.progressStyle = ko.computed(function(){
			return 'width:' + self.progressValue() + '%;';
		});
	};
	
	var _addWorkViewModel = function(self){
		self.onlyMy = ko.observable(localStorage['onlyMy'] === 'true');
		self.onlyMy.subscribe(function(value){
			localStorage['onlyMy'] = value;
			all.issues.valueHasMutated();
		});
		
		self.unassignedOpenIssues = ko.observableArray([]);
		self.unassignedOpenIssues.id_status = IssueStatus.STATUS_OPEN;
		self.unassignedOpenIssues.id_user = null;
		
		self.resolvedIssues = ko.observableArray([]);
		self.resolvedIssues.id_status = IssueStatus.STATUS_RESOLVED;
		
		self.verifiedIssues = ko.observableArray([]);
		self.verifiedIssues.id_status = IssueStatus.STATUS_VERIFIED;
		
		self.developers = ko.computed(function(){
			if(self.onlyMy()){
				return [user()];
			}
			return all.users();
		});
		
		// Распределяем Задачи по спискам
		all.issues.subscribe(function(){
			var unassignedOpenIssues = [];
			var resolvedIssues = [];
			var verifiedIssues = [];
			ko.utils.arrayForEach(all.issues(), function(issue){
				if(!issue.isRejected()){
					if(issue.assignee() == null && issue.isOpen()){
						unassignedOpenIssues.push(issue);
					}
					if(issue.isResolved()){
						if(self.onlyMy()){
							if(issue.assignee() != null && issue.assignee().id() == user().id()){
								resolvedIssues.push(issue);
							}
						}
						else{
							resolvedIssues.push(issue);
						}
					}
					if(issue.isVerified()){
						if(self.onlyMy()){
							if(issue.assignee() != null && issue.assignee().id() == user().id()){
								verifiedIssues.push(issue);
							}
						}
						else{
							verifiedIssues.push(issue);
						}
					}
				}
			});
			unassignedOpenIssues.sort(compareIssues);
			resolvedIssues.sort(compareIssues);
			verifiedIssues.sort(compareIssues);
			
			self.unassignedOpenIssues(unassignedOpenIssues);
			self.resolvedIssues(resolvedIssues);
			self.verifiedIssues(verifiedIssues);
		});
		all.issues.valueHasMutated();
		
		self.onDropInWorkCallback = function(arg){
			var issueStatus = all.issueStatuses.getById(arg.targetParent.id_status);
			if(typeof(arg.targetParent.id_user) !== 'undefined'){
				var user = all.users.getById(arg.targetParent.id_user);
				arg.item.assignee(user);
			}
			arg.item.update();
		};
	};
	
	var _addPlanViewModel = function(self){
		// Мусор - отклоненные задачи
		self.trashIssues = ko.observableArray([]);
		self.trashIssuesInfo = ko.computed(function(){
			var duration = 0;
			var number = self.trashIssues().length;
			ko.utils.arrayForEach(self.trashIssues(), function(issue){
				duration += issue.estimate();
			});
			return number + ' ' + declensionOfNumber(number, ['задача', 'задачи', 'задач']) + ': ' + duration + ' ч';
		});
		// Фильтруем нераспределенные задачи
		self.unscheduledIssues = ko.observableArray([]);
		self.unscheduledIssues.id_chunk = null;
		// Распределяем Задачи по спискам
		all.issues.subscribe(function(){
			var unscheduledIssues = [];
			ko.utils.arrayForEach(all.issues(), function(issue){
				// Если в мусорке
				if(issue.isRejected()){
					self.trashIssues.push(issue);
				}
				// Если не распределена
				else if(issue.isUnscheduled()){
					unscheduledIssues.push(issue);
				}
			});
			unscheduledIssues.sort(compareIssues);
			self.unscheduledIssues(unscheduledIssues);
		});
		/**
		 * Функционал
		 */
		// Обработчик события перетаскивания задачи
		self.onDropCallback = function (arg) {
			var chunk = all.chunks.getById(arg.targetParent.id_chunk);
			arg.item.setNotRejected();
			arg.item.chunk(chunk);
			arg.item.update();
			
		};
		// Обработчик события перетаскивания задачи в мусорку
		self.onDropToTrashCallback = function(arg){
			arg.item.setRejected();
			arg.item.update();
		};
	};
	
	// ViewModel - объект, свойства которого будут использоваться на странице План
	var PlanViewModel = function() {
		/**
		 * Инициализация
		 */
		var self = this;
		// Данные в виде JSON заранее помещаем в элемент
		// с атрибутом name=data, чтобы можно было работать с данными
		// внутри JS-кода
		var json = $.parseJSON($('[name=data]').val());
		$('[name=data]').remove();
		// В массиве полученных данных обязательно должен быть Проект
		// План строится на основе выбранного проекта
		self.project = ko.observable(new Project(json.project));
		// Заполнение глобальных данных (задач, этапов, проектов и т.д.)
		_fillGlobalData(json);
		
		/**
		 * Работа с Задачами
		 */
		// Создание задачи
		self.addIssue = function(issue, e){
			issue = new Issue();
			issue.project(self.project());
			self.editIssue(issue, e);
		};
		// Редактирование задачи
		self.editIssue = function(issue, e){
			if(e) e.preventDefault();
			var header = issue.isNewRecord() ? 'Создать задачу' : 'Редактировать задачу';
			var method = issue.isNewRecord() ? 'create' : 'update';
			modal.go({
				title:header,
				name:'issueModal',
				data: {
					issue: issue
				},
				// Функция, которая выполняется при нажатии кнопки "Сохранить"
				// в модальном окне
				onSave: function(){
					issue[method]({
						success: function(){
							// Если новая задача - то добавляем ее в списки
							if(issue.isNewRecord()){
								all.issues.push(issue);
								if(issue.isUnscheduled()){
									self.unscheduledIssues.push(issue);
								}
							}
							modal.hide();
						}
					});
				}
			});
		};
		
		/**
		 * Работа с Этапами
		 */
		// Создание этапа
		self.addChunk = function(chunk, e){
			chunk = new Chunk();
			chunk.project(self.project());
			self.editChunk(chunk, e);
		};
		// Редактирование этапа
		self.editChunk = function(chunk, e){
			if(e) e.preventDefault();
			var header = chunk.isNewRecord() ? 'Создать этап' : 'Редактировать этап';
			var method = chunk.isNewRecord() ? 'create' : 'update';
			modal.go({
				title:header,
				name:'chunkModal',
				data: {
					chunk: chunk
				},
				// Функция, которая выполняется при нажатии кнопки "Сохранить"
				// в модальном окне
				onSave: function(){
					chunk[method]({
						success: function(){
							// Если этап новый - то добавляем его в список
							if(chunk.isNewRecord()){
								all.chunks.push(chunk);
							}
							modal.hide();
						}
					});
				}
			});
		};
		// Удаление этапа
		self.deleteChunk = function(chunk, e){
			e.preventDefault();
			// Спрашиваем подтверждение
			if(confirm('Вы уверены, что хотите удалить этап?')){
				// Удаляем этап из БД
				chunk.delete({
					success: function(){
						// Все, находящиеся задачи внутри удаленного этапа
						// переводим в нераспределенные
						ko.utils.arrayForEach(chunk.issues(), function(issue){
							issue.chunk(null);
							self.unscheduledIssues.push(issue);
						});
						// Удаляем из списка
						all.chunks.remove(chunk);
					}
				});
			}
		};
		
		// Переключение режимов
		self.modes = [
			{name:'План',id:'plan'},
			{name:'Работа',id:'work'},
			{name:'Статистика',id:'statistic'}
		];
		self.selectedMode = ko.observable(self.modes[localStorage['plan.mode'] || 0]);
		self.selectMode = function(mode){
			self.selectedMode(mode);
			localStorage['plan.mode'] = self.modes.indexOf(mode);
		};
		
		// Расширяем функционал вью модели (раздел План)
		_addPlanViewModel(self);
		
		// Расширяем функционал вью модели (раздел Работа)
		_addWorkViewModel(self);
		
		// Расширяем функционал вью модели (раздел Статистика)
		_addStatisticViewModel(self);
	};
	
	// Применяем ViewModel к странице
	ko.applyBindings(new PlanViewModel());
});
